home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr40 / x1j4_src.zip / IPROUTE.C < prev    next >
Text File  |  1995-01-17  |  42KB  |  1,493 lines

  1. /*****************************************************************************/
  2. /*                                              */
  3. /*                                         */
  4. /*    *****              *****                      */
  5. /*     *****            *****                         */
  6. /*       *****          *****                         */
  7. /*         *****        *****                         */
  8. /*  ***************      ***************                     */
  9. /*  *****************    *****************                     */
  10. /*  ***************      ***************                     */
  11. /*         *****        *****       TheNet                    */
  12. /*       *****          *****       Portable. Compatible.         */
  13. /*     *****            *****       Public Domain             */
  14. /*    *****              *****    G8KBB                  */
  15. /*                                         */
  16. /* This software is public domain ONLY for non commercial use                */
  17. /*                                                                           */
  18. /*                                         */
  19. /*****************************************************************************/
  20.  
  21. /* Level 3, Internet Gateway                             */
  22. /* Version 1.00                                                              */
  23. /* Dave Roberts G8KBB, 7, Rowanhayes Close, Ipswich, England             */
  24. /* 10-April-91                                     */
  25. /* This software is released into the public domain on the understanding
  26.  * that it is to be used only for non life threatening, amateur, non 
  27.  * commercial purposes only. 
  28.  * It has been written expressly for use in self tuition of
  29.  * people in amateur radio communications only. It is NOT claimed that this
  30.  * software works correctly. 
  31.  *
  32.  * USELONG, if defined, causes long integers to be used where appropriate
  33.  * so failing to define it will avoid longs completely !
  34.  *
  35.  * September 1993 - released as TheNet X-1J
  36.  */
  37.  
  38. #include "all.h"
  39. #include "tntyp.h"        /* Definition of structures             */
  40. #include "ip.h"    
  41. #include "icmp.h"
  42. #ifdef BANKED
  43. #define EXTERN extern
  44. #else
  45. #define EXTERN
  46. #endif
  47.  
  48. #include "ipv.h"
  49.  
  50. /*---------------------------------------------------------------------------*/
  51. /* Strings etc                                     */
  52.  
  53. /* These are the interface handlers.
  54.  * Number Interface
  55.  *  0        Netrom
  56.  *  1        port 0 AX.25
  57.  *  2        port 1 AX.25
  58.  *
  59.  * The order MUST match the names in if_names[] in tnl7ip.c
  60.  */
  61.  
  62. I_FACE interfaces[] =
  63. {
  64. #ifdef MOD_MTU
  65.     nr_iface, &mtu_ipn, ARP_NETROM, 0,
  66.     l2_iface, &mtu_ip0, ARP_AX25,   HDLCPORT,
  67.     l2_iface, &mtu_ip1, ARP_AX25,   ASYNPORT,
  68. #else
  69.     nr_iface, 256-20, ARP_NETROM, 0,
  70.     l2_iface, 256,    ARP_AX25,   HDLCPORT,
  71.     l2_iface, 256,    ARP_AX25,   ASYNPORT,
  72. #endif
  73. };
  74.  
  75. char nodigi[] = { '\000' };
  76. char QST[] = { 'Q','S','T',' ',' ',' ','\140' };
  77.  
  78. /* ***************************************************************************
  79.  * Function    : ipinit
  80.  *
  81.  * Inputs    : none
  82.  *
  83.  * Returns     : none
  84.  *
  85.  * Operation    : Initialisation of IP gateway on reset of the TNC
  86.  *
  87.  * -------------------------------------------------------------------------*/
  88.  
  89. VOID    ipinit()            /* Router initialisation         */
  90. {
  91.     register int i;
  92.  
  93.      inithd(&iprxfl);    
  94.     inithd(&arprxfl);
  95.  
  96.     if (!iswarm())            /* Warmstart then skip             */
  97.     {
  98.         inithd(&IP_Routes);
  99.         inithd(&Arp_tab);
  100. #ifdef USELONG
  101.         my_ip_addr.Long = DEFMYIPADDR.Long;    /* node IP address */
  102.         bcast_ip_addr.Long = DEFIPBCAST.Long;    /* broadcast addr  */
  103. #else
  104.         my_ip_addr.Short[1] = DEFMYIPADDR.Short[1];    /* node IP  */
  105.         my_ip_addr.Short[0] = DEFMYIPADDR.Short[0];    /* ..address*/
  106.         bcast_ip_addr.Short[1] = DEFIPBCAST.Short[1];    /* broadcast*/
  107.         bcast_ip_addr.Short[0] = DEFIPBCAST.Short[0];    /* ..address*/
  108. #endif
  109.         for( i=0; i<=NUMIPMIB; i++ )
  110.             Ip_mib[i].value.integer = 0;    /* clear IP stats    */
  111.         ipL2Modes = DEFIPL2MODES;        /* l2 modes  */
  112.         ARPrunning = ipForwarding = DEFIPENABLE;/* enable ip router  */
  113.         ipDefaultTTL = DEFIPTTL;        /* set default ttl   */
  114.         ipReasmTimeout = TLB;            /* reasm timeout     */
  115.         ARPcounter = ARPtimer = 60;
  116.     }
  117.     else                /* Warmstart                 */
  118.     {
  119.     }
  120.     IP_Route_Cache.route = NULLROUTE;    /* clear route cache */
  121. }
  122.  
  123. /* ***************************************************************************
  124.  * Function    : IP server programme. Called by main scheduler
  125.  *
  126.  * Inputs    : None
  127.  *
  128.  * Returns    : None
  129.  *
  130.  * Operation    : Reads all frames from ip receive queue and handles them.
  131.  *                Then calls ARP protocol handler with its frames
  132.  * -------------------------------------------------------------------------*/
  133. VOID ipserv()
  134. {
  135.     register mhtyp *mbhd;
  136.  
  137.     /* Firstly, run through the queued IP frames
  138.      */
  139.     while ((mbhd = (mhtyp *)iprxfl.lnext) != (mhtyp *) &iprxfl)
  140.     {
  141.         unlink( mbhd );
  142. #ifdef PK96
  143.         sta_led_on();
  144. #endif
  145.         ip_route( mbhd );    /* pass to IP router routine */
  146. #ifdef PK96
  147.         sta_led_off();
  148. #endif
  149.         dealmb( mbhd );
  150.     }
  151.     /* Now run through the queued ARP frames
  152.      */
  153.     while ((mbhd = (mhtyp *)arprxfl.lnext) != (mhtyp *) &arprxfl)
  154.     {
  155.         unlink( mbhd );
  156.         arp_service( mbhd );    /* pass to IP router routine */
  157.         dealmb( mbhd );
  158.     }
  159. }
  160.  
  161.  
  162. /* ***************************************************************************
  163.  * Function    : IP router for a single frame. Called by ip server
  164.  *
  165.  * Inputs    : Pointer to frame to be routed
  166.  *
  167.  * Returns    : None
  168.  *
  169.  * Operation    : Forwards frame or returns an error ( ICMP ) frame.
  170.  *                Fragments the frame if sub layer demands it
  171.  * -------------------------------------------------------------------------*/
  172. VOID    ip_route( frame )        /* Internet server                 */
  173. mhtyp *frame;
  174. {
  175.     register int i;                /* a counter of general nature      */
  176.     register mhtyp *mbhd = frame;    /* pointer to frame using a register*/
  177.     register mhtyp *tbp;        /* pointer to frame for outputting  */
  178.     char *rxnxt;            /* temp for saving mbhd position    */
  179. #ifndef BANKED
  180. static    IP ip;                /* structure for decoded ip header  */
  181. #endif
  182.     int strict;            /* option sets for strict routing   */
  183.     ipaddr gateway;            /* addr of next IP router for frame */
  184.     IP_ROUTE *rp;            /* pointer used in finding route    */
  185.     unsigned length;        /* length of data portion of frame  */
  186.     unsigned offset;         /* offset in fragmentation routine  */
  187.     BOOLEAN rxbroadcast;        /* set denotes broadcast frame      */
  188.     BOOLEAN mf_flag;        /* more flag in fragmentation       */
  189.     unsigned char *opt, *ptr;    /* pointers in option handling      */
  190.     unsigned char opt_len;        /* length in option handling        */
  191.     unsigned ip_len;        /* ip header length                 */
  192.     unsigned mtu;            /* max port packet size for output  */
  193.  
  194.     if(((unsigned char)mbhd->pid != PID_IP) || !ipForwarding )
  195.         return;
  196.     rxnxt = mbhd->nxtchr;        /* Save pointers to IP hdr start    */
  197.     ip_len = getchr( mbhd );        /* get length & version byte*/
  198.     ip.version = ( ip_len >> 4 ) & 0x0f;     /* extract version number   */
  199.     ip_len = ( ip_len & 0x0f ) << 2;    /* and correct length  */
  200.     mbhd->nxtchr = rxnxt;            /* reinstate the pointer */
  201.     if( ( mbhd->putcnt - (--mbhd->getcnt) ) < IPLEN
  202.         ||
  203.         ip_len < IPLEN
  204.         ||
  205.         ip.version != IPVERSION
  206.         ||
  207.         cksum( NULLHEADER, mbhd, ip_len ) != 0 )
  208.     {
  209.         ipInHdrErrors++;
  210.         return;
  211.     }
  212.  
  213.     /* Now extract frame IP header
  214.      * This is akin to ntohip() in NOS
  215.      */
  216.     getchr( mbhd );                /* skip length/version      */
  217.     ip.tos = getchr( mbhd );
  218.     ip.length = get16( mbhd );
  219.     ip.id = get16( mbhd );
  220.     ip.offset = get16( mbhd );
  221.     ip.flags.mf = ( ip.offset & 0x2000 ) ? 1 : 0;
  222.     ip.flags.df = ( ip.offset & 0x4000 ) ? 1 : 0;
  223.     ip.offset = ( ip.offset & 0x1fff ) << 3;
  224.     ip.ttl = getchr( mbhd );
  225.     ip.protocol = getchr( mbhd );
  226.     ip.checksum = get16( mbhd );
  227.     ip.source.Short[1] = get16( mbhd );
  228.     ip.source.Short[0] = get16( mbhd );
  229.     ip.dest.Short[1] = get16( mbhd );
  230.     ip.dest.Short[0] = get16( mbhd );
  231.  
  232.     /* If this is a broadcast packet, set flag 
  233.      * Note we do not do port addressing here !
  234.      */
  235.     rxbroadcast = is_broadcast_address( &ip.dest );
  236.  
  237.     /* extract optional options from frame
  238.      */
  239.     if( (ip.optlen = ip_len - IPLEN ) != 0 )
  240.         for( i=0; i < ip.optlen; i++ )
  241.             ip.options[i] = getchr( mbhd );
  242.     length = ip.length - ip_len;
  243. /*    trim_mbuf( don't bother with this in this version ! );
  244. */
  245.     if( !rxbroadcast && nmbfre < 256 )
  246.         icmp_output( &ip, mbhd, ICMP_QUENCH, 0, NULLICMP );
  247.  
  248.     /* handle options here
  249.      */
  250.     strict = 0;
  251.     for( opt = ip.options; opt < &ip.options[ip.optlen]; opt += opt_len )
  252.     {
  253.         opt_len = opt[1];
  254.         switch( opt[0] & OPT_NUMBER )
  255.         {
  256.             case IP_EOL:
  257.                 goto no_opt;
  258.             case IP_NOOP:
  259.                 opt_len = 1;
  260.                 break;
  261.             case IP_SSROUTE:
  262.                 strict = 1;
  263.             case IP_LSROUTE:
  264.                 if( !is_my_ip_addr( &ip.dest ) )
  265.                     break;
  266.                 if( opt[2] >= opt_len )
  267.                     break;
  268.                 ptr = opt+opt[2]-1;
  269.                 for( i=0; i<4; i++ )
  270.                 {
  271.                     ip.dest.Bytes[3-i] = ptr[i];
  272.                     ptr[i] = my_ip_addr.Bytes[3-i];
  273.                 }
  274.                 opt[2] += 4;
  275.                 break;
  276.             case IP_RROUTE:
  277.                 if( opt[2] >= opt_len )
  278.                 {
  279.                     if( !rxbroadcast )
  280.                     {
  281.                         union icmp_args icmp_args;
  282.                         
  283.                         icmp_args.pointer = IPLEN+opt-ip.options;
  284.                         icmp_output(&ip,mbhd,ICMP_PARAM_PROB,0,&icmp_args);
  285.                     }
  286.                     return;
  287.                 }
  288.                 ptr = opt+opt[2]-1;
  289.                 for( i=0; i<4; i++ )
  290.                     ptr[i] = my_ip_addr.Bytes[3-i];
  291.                 opt += 4;
  292.                 break;
  293.         }
  294.     }
  295. no_opt:
  296.     if( ( is_my_ip_addr( &ip.dest ) ) || rxbroadcast )
  297.     {
  298.         if( !rxbroadcast && !ip.flags.mf && ip.offset == 0 &&
  299.             ip.protocol == ICMP_PTCL )
  300.         {
  301.             icmp_input( &ip, mbhd );
  302.             ipInReceives++;
  303.             return;
  304.         }
  305.         else
  306.         {
  307.             if( !rxbroadcast )
  308.                 icmp_output( &ip, mbhd, ICMP_DEST_UNREACH, 
  309.                              ICMP_PROT_UNREACH, NULLICMP );
  310.             ipInUnknownProtos++;
  311.             return;
  312.         }
  313.     }
  314.  
  315.     /* if( i_iface != NULLIF )  etc etc */
  316.  
  317.     ipForwDatagrams++;
  318.  
  319.     /* timeout - kill & return error frame to sender
  320.      */
  321.     if( --ip.ttl == 0 )        
  322.     {
  323.         icmp_output( &ip, mbhd, ICMP_TIME_EXCEED, 0, NULLICMP );
  324.         ipInHdrErrors++;
  325.         return;
  326.     }
  327.  
  328.     /* find entry in routing table for this frame.
  329.      * If there isn't one - then return an error & trash frame
  330.      */
  331.     if( ( rp = rt_find( &ip.dest ) ) == NULLROUTE )
  332.     {
  333.         icmp_output( &ip, mbhd, ICMP_DEST_UNREACH, 
  334.                      ICMP_HOST_UNREACH, NULLICMP );
  335.         ipOutNoRoutes++;
  336.         return;
  337.     }
  338.  
  339.     /* rp->uses++ */
  340.     /* redirection goes here if wanted */
  341.  
  342.     /* Compute the next IP router to send to ( ie the gateway )
  343.      * If the route table entry has no gateway, use destination
  344.      * If the gateway is not the destination, and strict routing
  345.      * has been called for, then error !
  346.      */
  347. #ifdef USELONG
  348.     gateway.Long = rp->gateway.Long == 0L ? ip.dest.Long : rp->gateway.Long;
  349.     if( strict && gateway.Long != ip.dest.Long )
  350. #else
  351.     i = (rp->gateway.Short[0] == 0) && ( rp->gateway.Short[1] == 0 );
  352.     gateway.Short[0] = i ? ip.dest.Short[0] : rp->gateway.Short[0];
  353.     gateway.Short[1] = i ? ip.dest.Short[1] : rp->gateway.Short[1];
  354.     if( strict && !( ( gateway.Short[0] == ip.dest.Short[0] ) &&
  355.                      ( gateway.Short[1] == ip.dest.Short[1] ) ) )
  356. #endif
  357.     {
  358.         icmp_output( &ip, mbhd, ICMP_DEST_UNREACH, 
  359.                      ICMP_ROUTE_FAIL, NULLICMP );
  360.         ipOutNoRoutes++;
  361.         return;
  362.     }
  363.  
  364.     /* bomb out if a funny has happened ( to preserve node integrity )
  365.      */
  366.     if( rp->interface >= MAXINTERFACES )
  367.         return;
  368.  
  369.     /* mtu for interface determines whether frame needs fragmentation
  370.      */
  371. #ifdef MOD_MTU
  372.     mtu = *(interfaces[rp->interface].mtu);
  373. #else
  374.     mtu = interfaces[rp->interface].mtu;
  375. #endif
  376.     if( ip.length <= mtu  )
  377.     {
  378.         tbp = htonip( &ip, mbhd, 0 );
  379. /*        if( tbp == NULLBUF )
  380.             return;
  381. */        (*interfaces[rp->interface].func)( tbp, rp->interface,
  382.             &gateway, ip.tos );
  383.         return;
  384.     }
  385.  
  386.     /* fragmentation needed for here on.
  387.      * First point -if it is marked don't fragment, we have a problem
  388.      */
  389.     if( ip.flags.df )
  390.     {
  391.         union icmp_args icmp_args;
  392.         
  393.         icmp_args.mtu = mtu;
  394.         icmp_output(&ip,mbhd,ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED,&icmp_args );
  395.         ipFragFails++;
  396.         return;
  397.     }
  398.  
  399.     /* prepare for fragmentation & go for it !
  400.      */
  401.     offset = ip.offset;
  402.     mf_flag = ip.flags.mf;
  403.     while( length != 0 )
  404.     {
  405.         unsigned fragsize;
  406.         
  407.         ip.offset = offset;
  408.         if( length + ip_len <= mtu )
  409.         {
  410.             fragsize = length;
  411.             ip.flags.mf = mf_flag;
  412.         }
  413.         else
  414.         {
  415.             fragsize = (mtu - ip_len ) & 0xfff8;
  416.             ip.flags.mf = 1;
  417.         }
  418.         ip.length = fragsize + ip_len;
  419.         tbp = htonip( &ip, NULLBUF, 0 );
  420.         for( i=fragsize; i != 0; i-- )
  421.             putchr( getchr( mbhd ), tbp );
  422.         (*interfaces[rp->interface].func)( tbp, rp->interface,
  423.             &gateway, ip.tos );
  424.         ipFragCreates++;
  425.         offset += fragsize;
  426.         length -= fragsize;
  427.     }
  428.     ipFragOKs++;
  429.     return;
  430. }
  431.  
  432. /* ***************************************************************************
  433.  * Function    : Determine if this address is my address
  434.  *
  435.  * Inputs    : pointer to address to be checked
  436.  *
  437.  * Returns    : TRUE if addresses match and an address has been set
  438.  *          FALSE if my address zero or no address match
  439.  *
  440.  * Operation    : 
  441.  * -------------------------------------------------------------------------*/
  442. is_my_ip_addr( address )
  443. register ipaddr *address;
  444. {
  445. #ifdef USELONG
  446.     return( my_ip_addr.Long != 0L && my_ip_addr.Long == address->Long );
  447. #else
  448.     if( (my_ip_addr.Short[0] == 0) && (my_ip_addr.Short[1] == 0) )
  449.         return( 0 );
  450.     return( (my_ip_addr.Short[0] == address->Short[0]) && 
  451.             (my_ip_addr.Short[1] == address->Short[1]) );
  452. #endif
  453. }
  454.  
  455. /* ***************************************************************************
  456.  * Function    : Check whether this address is the IP broadcast_ip address 
  457.  *
  458.  * Inputs    : Pointer to IP address
  459.  *
  460.  * Returns    : TRUE if my address set and addresses match exactly
  461.  *          FALSE otherwise
  462.  *
  463.  * Operation    :
  464.  * -------------------------------------------------------------------------*/
  465. is_broadcast_address( address )
  466. register ipaddr *address;
  467. {
  468. #ifdef USELONG
  469.     return( bcast_ip_addr.Long != 0L && bcast_ip_addr.Long == address->Long );
  470. #else
  471.     if( (bcast_ip_addr.Short[0] == 0) && (bcast_ip_addr.Short[1] == 0) )
  472.         return( 0 );
  473.     return( (bcast_ip_addr.Short[0] == address->Short[0]) && 
  474.             (bcast_ip_addr.Short[1] == address->Short[1]) );
  475. #endif
  476. }
  477.  
  478.  
  479. /* ***************************************************************************
  480.  * Function    : Try to find an entry in routing table for given target
  481.  *
  482.  * Inputs    : Pointer to IP address of target
  483.  *
  484.  * Returns    : Either a pointer to the table entry or a null pointer if none
  485.  *
  486.  * Operation    : First check the cache & return it if it is the one
  487.  *                Then search the table which is stored in descending order
  488.  *                of the number of significant bits, masking our address as
  489.  *                we go.
  490.  * -------------------------------------------------------------------------*/
  491. IP_ROUTE *rt_find( target )
  492. register ipaddr *target;
  493. {
  494.     register IP_ROUTE_MB *iprp;
  495.     ipaddr temp;
  496.     register unsigned bits;
  497.  
  498. #ifdef USELONG
  499.     if( IP_Route_Cache.target.Long == target->Long && 
  500.         IP_Route_Cache.route != NULLROUTE )
  501.         return( IP_Route_Cache.route );
  502.  
  503.     temp.Long = target->Long;
  504. #else
  505.     if( (IP_Route_Cache.target.Short[0] == target->Short[0] ) &&
  506.         (IP_Route_Cache.target.Short[1] == target->Short[1] ) &&
  507.         IP_Route_Cache.route != NULLROUTE )
  508.         return( IP_Route_Cache.route );
  509.  
  510.     temp.Short[0] = target->Short[0];
  511.     temp.Short[1] = target->Short[1];
  512. #endif
  513.     bits = 32;
  514.     for( iprp = (IP_ROUTE_MB *)IP_Routes.lnext;
  515.          iprp != (IP_ROUTE_MB *)&IP_Routes.lnext;
  516.          iprp = (IP_ROUTE_MB *)iprp->link.lnext )
  517.     {
  518. #ifdef USELONG
  519.         if( bits > iprp->route.bits )
  520.             temp.Long &= ~0L << ( 32 - ( bits = iprp->route.bits ) );
  521.         if( iprp->route.dest.Long == temp.Long )
  522.         {
  523.             IP_Route_Cache.target.Long = target->Long;
  524.             return ( (IP_Route_Cache.route = &iprp->route) );
  525.         }
  526. #else
  527.         if( bits > iprp->route.bits )
  528.             ip_mask( &temp, ( bits = iprp->route.bits ) );
  529.         if( (iprp->route.dest.Short[0] == temp.Short[0]) &&
  530.             (iprp->route.dest.Short[1] == temp.Short[1]) )
  531.         {
  532.             IP_Route_Cache.target.Short[0] = target->Short[0];
  533.             IP_Route_Cache.target.Short[1] = target->Short[1];
  534.             return ( (IP_Route_Cache.route = &iprp->route) );
  535.         }
  536. #endif
  537.     }
  538.     return( NULLROUTE );
  539. }
  540.  
  541. /* ***************************************************************************
  542.  * Function    : Convert host IP format header to network format
  543.  *
  544.  * Inputs    : pointer to header, buffer for data bytes & ckecksum flag
  545.  *
  546.  * Returns    : pointer to the new buffer in network format
  547.  *
  548.  * Operation    : Creates a new buffer, 
  549.  *                Transfers the header into it,
  550.  *                and unless the data buffer is a null pointer, copies data
  551.  * -------------------------------------------------------------------------*/
  552. mhtyp *htonip( iphdr, data, cflag )
  553. register IP *iphdr;
  554. mhtyp *data;
  555. BOOLEAN cflag;
  556. {
  557.     unsigned hdr_len;
  558.     register unsigned i;
  559.     register mhtyp *bufpoi;
  560.     unsigned fl_offs;
  561.     unsigned checksum;
  562.     char *ptr, *cksum_ptr;
  563.  
  564.     hdr_len = IPLEN + iphdr->optlen;
  565.     bufpoi = (mhtyp *)allocb();
  566.     putchr( ( IPVERSION << 4 ) | ( hdr_len >> 2 ), bufpoi );
  567.     putchr( iphdr->tos, bufpoi );
  568.     put16( iphdr->length, bufpoi );
  569.     put16( iphdr->id, bufpoi );
  570.     fl_offs = iphdr->offset >> 3;
  571.     if( iphdr->flags.df )
  572.         fl_offs |= 0x4000;
  573.     if( iphdr->flags.mf )
  574.         fl_offs |= 0x2000;
  575.     put16( fl_offs, bufpoi );
  576.     putchr( iphdr->ttl, bufpoi );
  577.     putchr( iphdr->protocol, bufpoi );
  578.     cksum_ptr = bufpoi->nxtchr;
  579.     put16( 0, bufpoi );
  580.     put16( iphdr->source.Short[1], bufpoi );
  581.     put16( iphdr->source.Short[0], bufpoi );
  582.     put16( iphdr->dest.Short[1], bufpoi );
  583.     put16( iphdr->dest.Short[0], bufpoi );
  584.     for( i=0; i< iphdr->optlen; i++ )
  585.         putchr( iphdr->options[i], bufpoi );
  586.     ptr = bufpoi->nxtchr;
  587.     i = bufpoi->putcnt;
  588.     rwndmb( bufpoi );
  589.     checksum = cflag ? iphdr->checksum : cksum(NULLHEADER,bufpoi,hdr_len);
  590.     bufpoi->nxtchr = cksum_ptr;
  591.     bufpoi->putcnt = 10;
  592.     put16( checksum, bufpoi);
  593.     bufpoi->nxtchr = ptr;
  594.     bufpoi->putcnt = i;
  595.     if( data != NULLBUF )
  596.     {
  597. #ifdef MODIFIED
  598.         mhtyp_copy( data, bufpoi );
  599. #else
  600.         i = data->putcnt - data->getcnt;
  601.         while( i-- )
  602.             putchr( getchr( data ) , bufpoi );
  603. #endif
  604.     }
  605.     return( bufpoi );
  606. }
  607.  
  608. /* ***************************************************************************
  609.  * Function    : Send an IP datagram. 
  610.  *          Modelled after the example interface on p 32 of RFC 791
  611.  *
  612.  * Inputs    : er, read the comments below !
  613.  *
  614.  * Returns    : nothing of any significance in this implementation
  615.  *
  616.  * Operation    : Create network format header, append data to it to
  617.  *                make a frame that looks like any other frame received
  618.  *                and drop it back into the ip receive queue for ip_route
  619.  * -------------------------------------------------------------------------*/
  620. int ip_send(source,dest,protocol,tos,ttl,bp,length,id,df)
  621. ipaddr *source;            /* source address */
  622. ipaddr *dest;            /* Destination address */
  623. unsigned protocol;            /* Protocol */
  624. unsigned tos;            /* Type of service */
  625. unsigned ttl;            /* Time-to-live */
  626. mhtyp *bp;        /* Data portion of datagram */
  627. unsigned short length;            /* Optional length of data portion */
  628. unsigned short id;            /* Optional identification */
  629. unsigned df;            /* Don't-fragment flag */
  630. {
  631.     register mhtyp *tbp;
  632.     IP ip;        /* Pointer to IP header */
  633.     register IP *ipptr = &ip;
  634. #ifndef BANKED
  635.     static unsigned short id_cntr;    /* Datagram serial number */
  636. #endif
  637.  
  638.     ipOutRequests++;
  639.  
  640. /*    if(*source == INADDR_ANY)            AAAARRRRRGGGHHHHH !!!
  641.         source.Long = my_ip_addr.Long;
  642. */    if(length == 0 && bp != NULLBUF)
  643.         length = bp->putcnt - bp->getcnt;
  644.  
  645.     /* Fill in IP header */
  646.     ipptr->tos = tos;
  647.     ipptr->length = IPLEN + length;
  648.     ipptr->id = ( id == 0 ) ? id_cntr++ : id;
  649.     ipptr->offset = 0;
  650.     ipptr->flags.mf = 0;
  651.     ipptr->flags.df = df;
  652.     ipptr->ttl = ( ttl == 0 ) ? ipDefaultTTL : ttl;
  653.     ipptr->protocol = protocol;
  654. #ifdef USELONG
  655.     ipptr->source.Long = source->Long;
  656.     ipptr->dest.Long = dest->Long;
  657. #else
  658.     ipptr->source.Short[0] = source->Short[0];
  659.     ipptr->source.Short[1] = source->Short[1];
  660.     ipptr->dest.Short[0] = dest->Short[0];
  661.     ipptr->dest.Short[1] = dest->Short[1];
  662. #endif
  663.     ipptr->optlen = 0;
  664.     tbp = htonip(&ip,bp,0);
  665.     dealmb(bp);
  666. /*    if( tbp == NULLBUF)
  667.         return( -1 );
  668. */    tbp->pid = PID_IP;
  669.     rwndmb( tbp );
  670.     relink( tbp, iprxfl.lprev );
  671.     return(0);
  672. }
  673.  
  674. /* ***************************************************************************
  675.  * Function    : ip router interface handler for netrom interface
  676.  *
  677.  * Inputs    : frame to send, interface handle, gateway address & flags
  678.  *
  679.  * Returns    : nothing
  680.  *
  681.  * Operation    : The frame is sent to the netrom interface, assuming that
  682.  *                the arp table contains an entry for the gateway that will
  683.  *                tell us what node callsign to use !
  684.  *                The frame is sent by appending it to the L3 send queue
  685.  * -------------------------------------------------------------------------*/
  686. unsigned nr_iface( mhbp, iface, gateway, tos )
  687. mhtyp *mhbp;
  688. unsigned iface;
  689. ipaddr *gateway;
  690. unsigned tos;
  691. {
  692.     register unsigned i;
  693.     register mhtyp *mb;
  694.     register ARP_TAB *arp;
  695.  
  696.     /* check if there is a netrom entry in arp table. If so, then
  697.      * check if there is a corresponding netrom node entry and set
  698.      * despoi to point to its identity
  699.      */
  700.     if( (arp = res_arp( gateway, ARP_NETROM ) ) != NULLARP &&
  701.         iscall( arp->callsign ) )
  702.     {
  703.         l4pidx = l4pcid = NR_PROTO_IP;    /* netrom IP family         */
  704.         l4ahd2 = l4ahd3 = 0;        /* these are unused for IP  */
  705.         l4aopc = NR4_OP_PID;        /* netrom proto extension   */
  706.         mb = gennhd();            /* create a L4 & L3 header  */
  707.         rwndmb( mhbp );            /* rewind to start for send */
  708. #ifdef MODIFIED
  709.         mhtyp_copy( mhbp, mb );
  710. #else
  711.         i = mhbp->putcnt - mhbp->getcnt;/* then copy frame onto hdr */
  712.         while( i-- )
  713.             putchr( getchr( mhbp ), mb );
  714. #endif
  715.         mb->l2lnk = despoi;        /* link points to dest node */
  716.         relink( mb, l3txl.lprev );    /* and queue it !           */
  717.     }
  718.     dealmb( mhbp );
  719. }
  720.  
  721. /* ***************************************************************************
  722.  * Function    : AX.25 handler for ip router
  723.  *
  724.  * Inputs    : as for above interface to netrom
  725.  *
  726.  * Returns    : nothing
  727.  *
  728.  * Operation    : determine if dg or vc. Queue for sending as appropriate
  729.  * -------------------------------------------------------------------------*/
  730. unsigned l2_iface( mhbp, iface, gateway, tos )
  731. mhtyp *mhbp;
  732. unsigned iface;
  733. ipaddr *gateway;
  734. unsigned tos;
  735. {
  736.     register ARP_TAB *arp;
  737.     register unsigned cnt;
  738.     unsigned port;
  739.     register l2ltyp *l2poi;
  740.  
  741.     /* determine tnc port number, rewind buffer & set PID to IP
  742.      */
  743.     port = interfaces[iface].port;
  744.     rwndmb( mhbp );
  745.     mhbp->pid = PID_IP;
  746.  
  747.     /* find the arp entry. Die if none !
  748.      */
  749.     if( (arp = res_arp( gateway, ARP_AX25 ) ) == NULLARP )
  750.     {
  751.         arp_request( gateway, ARP_AX25, port );
  752.         dealmb( mhbp );
  753.     }
  754.  
  755.     /* Now check to see if we are going to DG or VC it
  756.      */
  757.     else if( (arp->dgmode & 1) || (( arp->dgmode == 0 ) && ( tos & DELAY || 
  758.              ( !( tos & RELIABILITY ) && ( ipL2Modes & (1<<port))))))
  759.     {
  760.         sdui( nodigi, arp->callsign, myid, port, mhbp );
  761.         dealmb( mhbp );
  762.     }
  763.     else /* virtual circuit */
  764.     {
  765.         /* Need to find current L2 connection or need to make one
  766.          */
  767.         for( l2poi = 0, cnt = 0, lnkpoi = &lnktbl[0]; 
  768.              cnt < MAXL2L; ++cnt, ++lnkpoi )
  769.         {
  770.             if( lnkpoi->state != 0 )
  771.             {
  772.                 if( cmpid( arp->callsign, lnkpoi->dstid ) &&
  773.                     cmpid( myid, lnkpoi->srcid ) &&
  774.                     lnkpoi->liport == port )
  775.                     break;
  776.             }
  777.             else if( (l2poi == 0 ) && ( lnkpoi->srcid[0] == 0 ) )
  778.                 l2poi = lnkpoi;
  779.         }
  780.  
  781.         /* either we have it or we are at the end, with no space
  782.          * or a pointer to the first free entry in the link list
  783.          */
  784.         if( cnt == MAXL2L )
  785.         {
  786.             if( l2poi != 0 )
  787.             {
  788.                 lnkpoi = l2poi;
  789.                 cpyid( lnkpoi->srcid, myid );
  790.                 cpyid( lnkpoi->dstid, arp->callsign );
  791.                 cpyidl(lnkpoi->viaid, nodigi );
  792.                 lnkpoi->liport = port;
  793.                 newlnk();
  794.             }
  795.             else /* no link and no space for one */
  796.             {
  797.                 dealmb( mhbp );
  798.                 return;
  799.             }
  800.         }
  801.         lnkpoi->tosend++;
  802.         relink( mhbp, lnkpoi->sendil.lprev );
  803.     }
  804. }
  805.  
  806.  
  807. /* ***************************************************************************
  808.  * Function    : find an arp entry for a given target and hardware type
  809.  *
  810.  * Inputs    : pointer to internet address and a hardware ( arp ) type
  811.  *
  812.  * Returns    : pointer to entry in arp table or a null pointer
  813.  *
  814.  * Operation    : linear search of table looking for a match
  815.  * -------------------------------------------------------------------------*/
  816. ARP_TAB *res_arp( target, hwtype )
  817. register unsigned hwtype;
  818. register ipaddr *target;
  819. {
  820.     register ARP_TAB_MB *arprp;
  821.  
  822.     for( arprp = (ARP_TAB_MB *)Arp_tab.lnext;
  823.          arprp != (ARP_TAB_MB *)&Arp_tab.lnext;
  824.          arprp = (ARP_TAB_MB *)arprp->link.lnext )
  825.         if( hwtype == arprp->arp.hwtype && 
  826. #ifdef USELONG
  827.             arprp->arp.dest.Long == target->Long )
  828. #else
  829.             arprp->arp.dest.Short[0] == target->Short[0] &&
  830.             arprp->arp.dest.Short[1] == target->Short[1] )
  831. #endif
  832.             return( &arprp->arp );
  833.     return( NULLARP );
  834. }
  835.  
  836. /* ***************************************************************************
  837.  * Function    : Get a sixteen bit word from buffer
  838.  *
  839.  * Inputs    : pointer to buffer
  840.  *
  841.  * Returns    : unsigned integer
  842.  *
  843.  * Operation    : reads two bytes into a structure & swaps in process.
  844.  * -------------------------------------------------------------------------*/
  845. unsigned get16( mbhd )
  846. register mhtyp *mbhd;
  847. {
  848.     union {
  849.         unsigned Short;
  850.         unsigned char Bytes[2];
  851.     } regs;
  852.     
  853.     regs.Bytes[1] = getchr( mbhd );
  854.     regs.Bytes[0] = getchr( mbhd );
  855.     return( regs.Short );
  856. }
  857.  
  858. /* ***************************************************************************
  859.  * Function    : Put an unsigned integer as two bytes in buffer
  860.  *
  861.  * Inputs    : value to put and pointer to buffer
  862.  *
  863.  * Returns    : nothing
  864.  *
  865.  * Operation    :
  866.  * -------------------------------------------------------------------------*/
  867. VOID put16( value, mbhd )
  868. register unsigned value;
  869. register mhtyp *mbhd;
  870. {
  871.     union {
  872.         unsigned Short;
  873.         unsigned char Bytes[2];
  874.     } regs;
  875.  
  876.     regs.Short = value;    
  877.     putchr( regs.Bytes[1], mbhd );
  878.     putchr( regs.Bytes[0], mbhd );
  879. }
  880.  
  881.  
  882. /* ***************************************************************************
  883.  * Function    : Return an ICMP response to the sender of a datagram.
  884.  *          Unlike most routines, the callER frees the mbuf.
  885.  *
  886.  * Inputs    : pointer to offending ip header, data, icmp codes & params
  887.  *
  888.  * Returns    : nothing in this version !
  889.  *
  890.  * Operation    : Did you ever hear the one about the vampire rabbit ?
  891.  *                Note lots of standard icmp bits are commented out.
  892.  * -------------------------------------------------------------------------*/
  893. int icmp_output(ip,data,type,code,args)
  894. IP *ip;        /* Header of offending datagram */
  895. register mhtyp *data;    /* Data portion of datagram */
  896. unsigned type,code;        /* Codes to send */
  897. union icmp_args *args;
  898. {
  899.     mhtyp *bp, *bp2;
  900.     ICMP icmp;            /* ICMP protocol header */
  901.     unsigned short length;        /* Total length of reply */
  902.     register unsigned short i;
  903.     char *rxnxt;
  904.  
  905.     if(ip == NULLIP)
  906.         return(-1);
  907.     if( (unsigned char)ip->protocol == ICMP_PTCL)
  908.     {
  909.         /* Peek at type field of ICMP header to see if it's safe to
  910.          * return an ICMP message
  911.          */
  912.         rxnxt = data->nxtchr;
  913.         i = getchr( data ) & 0xff;
  914.         data->nxtchr = rxnxt;
  915.         data->getcnt--;
  916.         switch( i )
  917.         {
  918.         case ICMP_ECHO_REPLY:
  919.         case ICMP_ECHO:
  920.         case ICMP_TIMESTAMP:
  921.         case ICMP_TIME_REPLY:
  922.         case ICMP_INFO_RQST:
  923.         case ICMP_INFO_REPLY:
  924.             break;    /* These are all safe */
  925.         default:
  926.             /* Never send an ICMP error message about another
  927.              * ICMP error message!
  928.              */
  929.             return(-1);
  930.         }
  931.     }
  932.     /* Compute amount of original datagram to return.
  933.      * We return the original IP header, and up to 8 bytes past that.
  934.      */
  935.     i = data->putcnt - data->getcnt;
  936.     if( i > 8 ) i = 8;
  937.     length = i + ICMPLEN + IPLEN + ip->optlen;
  938.  
  939.     /* Recreate and tack on offending IP header */
  940.     bp = htonip(ip, NULLBUF, 1);
  941.  
  942. /*    if( data == NULLBUF)
  943.     {
  944.         icmpOutErrors++;
  945.         return(-1);
  946.     }
  947. */
  948.     /* Take excerpt from data portion */
  949.     while( i-- )                /* i set in above !!! */
  950.         putchr( getchr( data ), bp );
  951.     icmp.type = type;
  952.     icmp.code = code;
  953.     icmp.args.unused = 0;
  954.  
  955.     switch( type )
  956.     {
  957. /*    case ICMP_ECHO:
  958.         icmpOutEchos++;
  959.         break;
  960.     case ICMP_ECHO_REPLY:
  961.         icmpOutEchoReps++;
  962.         break;
  963.     case ICMP_INFO_RQST:
  964.         break;
  965.     case ICMP_INFO_REPLY:
  966.         break;
  967.     case ICMP_TIMESTAMP:
  968.         icmpOutTimestamps++;
  969.         break;
  970.     case ICMP_ADDR_MASK:
  971.         icmpOutAddrMasks++;
  972.         break;
  973.     case ICMP_ADDR_MASK_REPLY:
  974.         icmpOutAddrMaskReps++;
  975.         break;
  976.     case ICMP_TIME_EXCEED:
  977.         icmpOutTimeExcds++;
  978.         break;
  979.     case ICMP_QUENCH:
  980.         icmpOutSrcQuenchs++;
  981.         break;
  982. */    case ICMP_PARAM_PROB:
  983. /*        icmpOutParmProbs++;
  984. */        icmp.args.pointer = args->pointer;
  985.         break;
  986.     case ICMP_REDIRECT:
  987. /*        icmpOutRedirects++;
  988. */        icmp.args.address = args->address;
  989.         break;
  990.     case ICMP_TIME_REPLY:
  991. /*        icmpOutTimestampReps++;
  992. */        icmp.args.echo.id = args->echo.id;
  993.         icmp.args.echo.seq = args->echo.seq;
  994.         break;
  995.     case ICMP_DEST_UNREACH:
  996.         if(icmp.code == ICMP_FRAG_NEEDED)
  997.             icmp.args.mtu = args->mtu;
  998. /*        icmpOutDestUnreachs++;
  999. */        break;
  1000.     }
  1001.     /* Now stick on the ICMP header */
  1002.     bp2 = htonicmp(&icmp,bp);
  1003.     dealmb( bp );
  1004. /*    if(bp2 == NULLBUF)
  1005.         return(-1);
  1006. */    return( ip_send(&my_ip_addr,&ip->source,ICMP_PTCL,ip->tos,0,bp2,length,0,0));
  1007. }
  1008.  
  1009. /* ***************************************************************************
  1010.  * Function    : Generate ICMP header in network byte order, link data, 
  1011.  *          compute checksum
  1012.  *
  1013.  * Inputs    : pointer to icmp header structure in host format
  1014.  *                and pointer to data to be appended
  1015.  *
  1016.  * Returns    : Pointer to new frame in network format
  1017.  *
  1018.  * Operation    : Well, there was this traveller in Transylvania,
  1019.  * -------------------------------------------------------------------------*/
  1020. mhtyp *htonicmp(icmp,data)
  1021. register ICMP *icmp;
  1022. mhtyp *data;
  1023. {
  1024.     register mhtyp *bp;
  1025.     unsigned short checksum;
  1026.     register unsigned putcnt;
  1027.     char *nxtchr, *cksum_ptr;
  1028.  
  1029.     bp = (mhtyp *)allocb();
  1030.     putchr( icmp->type, bp );
  1031.     putchr( icmp->code, bp );
  1032.     cksum_ptr = bp->nxtchr;
  1033.     put16( 0, bp );        /* Clear checksum */
  1034.  
  1035.     switch(icmp->type)
  1036.     {
  1037.     case ICMP_DEST_UNREACH:
  1038.         put16( 0, bp );
  1039.         if(icmp->code == ICMP_FRAG_NEEDED)
  1040.             /* Deering/Mogul max MTU indication */
  1041.             put16( icmp->args.mtu, bp);
  1042.         else
  1043.             put16( 0, bp);
  1044.         break;
  1045.     case ICMP_PARAM_PROB:
  1046.         putchr( icmp->args.pointer, bp );
  1047.         putchr( 0, bp );
  1048.         put16( 0, bp );
  1049.         break;
  1050.     case ICMP_REDIRECT:
  1051.         put16( icmp->args.address.Short[1], bp );
  1052.         put16( icmp->args.address.Short[0], bp );
  1053.         break;
  1054.     case ICMP_ECHO:
  1055.     case ICMP_ECHO_REPLY:
  1056.     case ICMP_TIMESTAMP:
  1057.     case ICMP_TIME_REPLY:
  1058.     case ICMP_INFO_RQST:
  1059.     case ICMP_INFO_REPLY:
  1060.         put16( icmp->args.echo.id, bp );
  1061.         put16( icmp->args.echo.seq, bp );
  1062.         break;
  1063.     default:
  1064.         put16( 0, bp );
  1065.         put16( 0, bp );
  1066.         break;
  1067.     }
  1068.     rwndmb( data );
  1069.     putcnt = data->putcnt;
  1070.     while( putcnt-- )
  1071.         putchr( getchr( data ) , bp );
  1072.  
  1073.     /* Compute checksum, and stash result */
  1074.     putcnt = bp->putcnt;
  1075.     rwndmb( bp );
  1076.     checksum = cksum(NULLHEADER,bp, bp->putcnt);
  1077.     bp->nxtchr = cksum_ptr;
  1078.     bp->putcnt = 2;
  1079.     put16( checksum, bp );
  1080.     bp->putcnt = putcnt;
  1081.     rwndmb( bp );
  1082.     return(bp);
  1083. }
  1084.  
  1085. /* ***************************************************************************
  1086.  * Function    : Reduced icmp input routine for echo only
  1087.  *
  1088.  * Inputs    : ip header decoded plus data in the ip frame
  1089.  *
  1090.  * Returns    : nothing
  1091.  *
  1092.  * Operation    : Perform a simple icmp input and ip receive function
  1093.  *                to allow ping ( icmp echo request / reply )
  1094.  *                If valid, uses ipsend to add to the send queue
  1095.  * -------------------------------------------------------------------------*/
  1096. VOID icmp_input( ip, bp )
  1097. register IP *ip;
  1098. register mhtyp *bp;
  1099. {
  1100.     mhtyp *tbp;
  1101.     register mhtyp *bp2;
  1102.     ICMP icmp;
  1103.     unsigned length, i;
  1104.  
  1105.     length = ip->length - IPLEN - ip->optlen;
  1106.     if( cksum( NULLHEADER, bp, length ) != 0 )
  1107.         return;
  1108.     if( bp->putcnt - bp->getcnt < 8 )
  1109.         return;
  1110.     icmp.type = getchr( bp );
  1111.     icmp.code = getchr( bp );
  1112.     if( icmp.type == ICMP_ECHO )
  1113.     {
  1114.         get16( bp );
  1115.         icmp.args.echo.id = get16( bp );
  1116.         icmp.args.echo.seq = get16( bp );
  1117.         icmp.type = ICMP_ECHO_REPLY;
  1118.         bp2 = allocb();
  1119.         if ( length > 8 )
  1120.         {
  1121.             i = length - 8;
  1122.             while( i-- )
  1123.                 putchr( getchr( bp ), bp2 );
  1124.         }
  1125.         tbp = htonicmp( &icmp, bp2 );
  1126.         dealmb( bp2 );
  1127.         ip_send( &ip->dest, &ip->source, ICMP_PTCL,
  1128.                  ip->tos, 0, tbp, length, 0, 0 );
  1129.     }
  1130. }
  1131.  
  1132. /* ***************************************************************************
  1133.  * Function    : Perform end-around-carry adjustment
  1134.  *
  1135.  * Inputs    : current checksum if using longs
  1136.  *                ( if not, it uses a static structure ! )
  1137.  *
  1138.  * Returns    : corrected unsigned integer checksum with carries
  1139.  *
  1140.  * Operation    : Add the accumulated carry bits into the lower 16 bits
  1141.  *                and keep doing it until you have no more carries
  1142.  * -------------------------------------------------------------------------*/
  1143. #ifdef USELONG
  1144. unsigned short eac(sum)
  1145. long sum;    /* Carries in high order 16 bits */
  1146. {
  1147.     register unsigned short csum;
  1148.  
  1149.     while((csum = sum >> 16) != 0)
  1150.         sum = csum + (sum & 0xffffL);
  1151.     return((unsigned short) (sum & 0xffffl));    /* Chops to 16 bits */
  1152. }
  1153.  
  1154. #else
  1155. unsigned short eac()
  1156. {
  1157.     register unsigned short csum;
  1158.  
  1159.     while( ( csum = ip_cksum.Short[1] ) != 0 )
  1160.     {
  1161.         ip_cksum.Short[1] = 0;
  1162.         addsum( csum );
  1163.     }
  1164.     return( ip_cksum.Short[0] );
  1165. }
  1166. #endif
  1167.  
  1168. /* ***************************************************************************
  1169.  * Function    : Checksum an mhtyp, with optional pseudo-header
  1170.  *
  1171.  * Inputs    : pseudo header, buffer to checksum and byte count
  1172.  *
  1173.  * Returns    : unsigned integer checksum with eac corrected
  1174.  *
  1175.  * Operation    : add up all bytes in a long, in perverse arpa way then eac
  1176.  * -------------------------------------------------------------------------*/
  1177. unsigned short cksum(ph,m,len)
  1178. register unsigned short len;
  1179. register struct pseudo_header *ph;
  1180. register mhtyp *m;
  1181. {
  1182.     long sum;
  1183.     unsigned getcnt;
  1184.     char *nxtchr;
  1185.  
  1186. #ifdef USELONG
  1187.     sum = 0L;
  1188. #else
  1189.     ip_cksum.Short[0] = ip_cksum.Short[1] = 0;
  1190. #endif
  1191.  
  1192.     /* Sum pseudo-header, if present */
  1193.     if(ph != NULLHEADER)
  1194.     {
  1195. #ifdef USELONG
  1196.         sum =  (unsigned)ph->source.Short[0];
  1197.         sum += (unsigned)ph->source.Short[1];
  1198.         sum += (unsigned)ph->dest.Short[0];
  1199.         sum += (unsigned)ph->dest.Short[1];
  1200.         sum += (unsigned)ph->protocol & 0xff;
  1201.         sum += (unsigned)ph->length;            
  1202. #else
  1203.         addsum( ph->source.Short[0] ); 
  1204.         addsum( ph->source.Short[1] );   
  1205.         addsum( ph->dest.Short[0] );     
  1206.         addsum( ph->dest.Short[1] );     
  1207.         addsum( ph->protocol & 0xff );   
  1208.         addsum( ph->length );
  1209. #endif
  1210.     }
  1211.  
  1212.     getcnt = m->getcnt;
  1213.     nxtchr = m->nxtchr;
  1214.     while( len > 0 )
  1215.     {
  1216.         if( len > 1 )
  1217.         {
  1218. #ifdef USELONG
  1219.             sum += (unsigned)get16( m );
  1220. #else
  1221.             addsum( get16( m ) );
  1222. #endif
  1223.             len -= 2;
  1224.         }
  1225.         else
  1226.         {
  1227. #ifdef USELONG
  1228.             sum += ( (unsigned)getchr( m ) << 8 ) & 0xff00 ;
  1229. #else
  1230.             addsum( ( getchr( m ) << 8 ) & 0xff00 );
  1231. #endif
  1232.             len--;
  1233.         }
  1234.     }
  1235.     m->getcnt = getcnt;
  1236.     m->nxtchr = nxtchr;
  1237.     /* Do final end-around carry, complement and return */
  1238. #ifdef USELONG
  1239.     return( (unsigned short)(~eac(sum) & 0xffff));
  1240. #else
  1241.     return( ~eac() );
  1242. #endif
  1243. }
  1244.  
  1245. /* ***************************************************************************
  1246.  * Function    : for those systems that avoid longs, mask an ip address
  1247.  *                off to (bits) bits
  1248.  *
  1249.  * Inputs    : pointer to address and number of bits to leave
  1250.  *
  1251.  * Returns    : nothing
  1252.  *
  1253.  * Operation    : perform ip style 32 bit masking as two shorts.
  1254.  * -------------------------------------------------------------------------*/
  1255.  
  1256. #ifndef USELONG
  1257.  
  1258. VOID ip_mask( targt, bits )
  1259. unsigned bits;
  1260. ipaddr *targt;
  1261. {
  1262.     register unsigned i = 32 - bits;
  1263.     register ipaddr *target = targt;
  1264.  
  1265.     if( i == 0 )
  1266.         return;
  1267.     else if( i < 16 )
  1268.         target->Short[0] &= ( ~0 << ( i ) );
  1269.     else
  1270.     {
  1271.         target->Short[0] = 0;
  1272.         if( i > 16 )
  1273.             target->Short[1] &= ( ~0 << ( i - 16 ) );
  1274.     }
  1275. }
  1276. #endif
  1277.  
  1278. /* ***************************************************************************
  1279.  * Function    : for those systems that avoid longs, add to checksum
  1280.  *
  1281.  * Inputs    : 16 bit unsigned to add to 32 bit checksum
  1282.  *
  1283.  * Returns    : nothing
  1284.  *
  1285.  * Operation    : add the value to the static checksum ( unsigned long )
  1286.  *                Note : for proper processors, #define does it with longs !
  1287.  * -------------------------------------------------------------------------*/
  1288. #ifndef addsum
  1289. #asm
  1290.     .z80
  1291.     public    addsum_
  1292.  
  1293. addsum_:    
  1294.     pop    hl
  1295.     pop    de
  1296.     push    de
  1297.     push    hl
  1298.     ld    hl,(ip_cksum_)
  1299.     add    hl,de
  1300.     ld    (ip_cksum_),hl
  1301.     ret    nc
  1302.     ld    hl,(ip_cksum_ + 2)
  1303.     inc    hl
  1304.     ld    (ip_cksum_ + 2 ),hl
  1305.     ret
  1306.  
  1307.     .8080
  1308. #endasm
  1309. #endif
  1310.  
  1311. /* the following routines are needed for the arp protocol handler
  1312.  */
  1313.  
  1314. /* ***************************************************************************
  1315.  * Function    : Main handler for ARP requests from the network
  1316.  *
  1317.  * Inputs    : pointer to the input frame from the L2 handler
  1318.  *
  1319.  * Returns    : Nothing.
  1320.  *
  1321.  * Outputs    : UI frame with the result of the processing ( if needed )
  1322.  *
  1323.  * Operation    : Unpack the frame. Check it is OK, and is either for us
  1324.  *                or for a published entry or a revarp request we can deal
  1325.  *                with. If it is, form the reply and send a UI frame.
  1326.  * -------------------------------------------------------------------------*/
  1327.  
  1328. VOID arp_service( mhbp )
  1329. mhtyp *mhbp;
  1330. {
  1331.     unsigned char arp_not_revarp;
  1332.     char *ptr;
  1333.     register mhtyp *mbhd = mhbp;
  1334.     register ARP_TAB *ap;
  1335.     register unsigned i;
  1336.     ARP_TAB_MB *atp;
  1337.  
  1338.     if( !ARPrunning || (unsigned char)mbhd->pid != PID_ARP )
  1339.         return;
  1340.     if(( arp.hardware = get16( mbhd )) != ARP_AX25 )
  1341.     {
  1342. /*        arp_stat.badtype++; */
  1343.         return;
  1344.     }
  1345.     if( (arp.protocol = get16( mbhd ) ) != PID_IP )
  1346.     {
  1347. /*        arp_stat.badtype++; */
  1348.         return;
  1349.     }
  1350.     arp.hwalen = getchr( mbhd );
  1351.     arp.pralen = getchr( mbhd );
  1352.     if( arp.hwalen > MAXHWALEN || arp.pralen != sizeof( ipaddr ) )
  1353.     {
  1354. /*        arp_stat.badlen++; */
  1355.         return;
  1356.     }
  1357.     arp.opcode = get16( mbhd );
  1358.     getfid( arp.shwaddr, mbhd );
  1359.     arp.sprotaddr.Short[1] = get16( mbhd );
  1360.     arp.sprotaddr.Short[0] = get16( mbhd );
  1361.     getfid( arp.thwaddr, mbhd );
  1362.     arp.tprotaddr.Short[1] = get16( mbhd );
  1363.     arp.tprotaddr.Short[0] = get16( mbhd );
  1364.     if( cmpid( arp.shwaddr, QST ) )
  1365.     {
  1366. /*        arp_stat.badaddr++; */
  1367.         return;
  1368.     }
  1369.  
  1370.     ap = res_arp( &arp.sprotaddr, arp.hardware );
  1371.  
  1372.     if( ((i=is_my_ip_addr( &arp.tprotaddr)) && ap == NULLARP ) 
  1373.         ||
  1374.         ( ap != NULLARP && ap->timer != 0 ) )
  1375.         arp_add( &arp.sprotaddr, arp.hardware, arp.shwaddr, 0, ARPtimer, 0 );
  1376.  
  1377.     if( arp.opcode == REVARP_REQUEST
  1378.         ||
  1379.         ( arp.opcode == ARP_REQUEST
  1380.           &&
  1381.           ( ( i /* = is_my_ip_addr( &arp.tprotaddr  ) */ )
  1382.             ||
  1383.             ( ( ap = res_arp( &arp.tprotaddr, arp.hardware )) != NULLARP
  1384.               && ap->publish_flag
  1385.             )
  1386.           )
  1387.         )
  1388.       )
  1389.     {
  1390.         arp_not_revarp = ( arp.opcode == ARP_REQUEST );
  1391.         if( !arp_not_revarp )
  1392.             for( atp =  ( ARP_TAB_MB * )Arp_tab.lnext;
  1393.                  atp != ( ARP_TAB_MB * )&Arp_tab.lnext;
  1394.                  atp =  ( ARP_TAB_MB * )atp->link.lnext )
  1395.                 if( ( i = cmpid( (ap=&(atp->arp))->callsign, arp.thwaddr ) ) )
  1396.                     break;
  1397.         if( arp_not_revarp || ( i && ap->publish_flag ) )
  1398.         {
  1399.             if( arp_not_revarp )
  1400.             {
  1401.                 cpyid( arp.thwaddr, arp.shwaddr );
  1402.                 /* if( arp.hardware == ARP_AX25 ) */
  1403.                     arp.thwaddr[arp.hwalen - 1 ] |= 1;
  1404.             }
  1405.             cpyid( arp.shwaddr, i ? myid : ap->callsign );
  1406. #ifdef USELONG
  1407.             arp.tprotaddr.Long = arp_not_revarp ? 
  1408.                 arp.sprotaddr.Long : ap->dest.Long;
  1409.             arp.sprotaddr.Long = i ? 
  1410.                 my_ip_addr.Long : ap->dest.Long;
  1411. #else
  1412.             arp.tprotaddr.Short[1] = arp_not_revarp ? 
  1413.                 arp.sprotaddr.Short[1] : ap->dest.Short[1];
  1414.             arp.tprotaddr.Short[0] = arp_not_revarp ? 
  1415.                 arp.sprotaddr.Short[0] : ap->dest.Short[0];
  1416.             arp.sprotaddr.Short[1] = i ? 
  1417.                 my_ip_addr.Short[1] : ap->dest.Short[1];
  1418.             arp.sprotaddr.Short[0] = i ? 
  1419.                 my_ip_addr.Short[0] : ap->dest.Short[0];
  1420. #endif
  1421.             arp.opcode = arp_not_revarp ? ARP_REPLY : REVARP_REPLY;
  1422.             arp_send( mhbp->l2port, arp.thwaddr );
  1423. /*            Arp_stat.inreq++;    */
  1424.         }
  1425.     }
  1426. }
  1427.  
  1428. /* ***************************************************************************
  1429.  * Function    : Send an ARP request/response frame to specified port ( L2 AX25 )
  1430.  *
  1431.  * Inputs    : pointer to the host format arp frame and L2 port number
  1432.  *
  1433.  * Returns    : Nothing.
  1434.  *
  1435.  * Outputs    : UI frame with the ARP request
  1436.  *
  1437.  * -------------------------------------------------------------------------*/
  1438.  
  1439.  
  1440. arp_send( port, hwaddr )
  1441. unsigned port;
  1442. char *hwaddr;
  1443. {
  1444.     register mhtyp *mbhd;
  1445.  
  1446.     mbhd = allocb();
  1447.     put16( arp.hardware, mbhd );
  1448.     put16( arp.protocol, mbhd );
  1449.     putchr( arp.hwalen, mbhd );
  1450.     putchr( arp.pralen, mbhd );
  1451.     put16( arp.opcode, mbhd );
  1452.     putfid( arp.shwaddr, mbhd );
  1453.     put16( arp.sprotaddr.Short[1], mbhd );
  1454.     put16( arp.sprotaddr.Short[0], mbhd );
  1455.     putfid( arp.thwaddr, mbhd );
  1456.     put16( arp.tprotaddr.Short[1], mbhd );
  1457.     put16( arp.tprotaddr.Short[0], mbhd );
  1458.     /* if( mbhd == NULLBUF ) return; */
  1459.     mbhd->pid = PID_ARP;
  1460.     rwndmb( mbhd );
  1461.     sdui( nodigi, hwaddr, myid, port, mbhd );
  1462.     dealmb( mbhd );
  1463. }
  1464.  
  1465. arp_request( gw, hwtype, port )
  1466. ipaddr *gw;
  1467. unsigned hwtype;
  1468. unsigned port;
  1469. {
  1470.     register unsigned i;
  1471.     register ipaddr *gateway = gw;
  1472.  
  1473.     arp.hardware = hwtype;
  1474.     arp.protocol = PID_IP;
  1475.     arp.hwalen = L2IDLEN;
  1476.     arp.pralen = sizeof( ipaddr );
  1477.     arp.opcode = ARP_REQUEST;
  1478.     cpyid( arp.shwaddr, myid );
  1479. #ifdef USELONG
  1480.     arp.sprotaddr.Long = my_ip_addr.Long;
  1481.     arp.tprotaddr.Long = gateway->Long;
  1482. #else
  1483.     arp.sprotaddr.Short[0] = my_ip_addr.Short[0];
  1484.     arp.sprotaddr.Short[1] = my_ip_addr.Short[1];
  1485.     arp.tprotaddr.Short[0] = gateway->Short[0];
  1486.     arp.tprotaddr.Short[1] = gateway->Short[1];
  1487. #endif
  1488.     for( i=0; i<L2IDLEN; i++ )
  1489.         arp.thwaddr[i] = 0;
  1490.     arp_send( port, QST );
  1491. }    
  1492.  
  1493.